package com.hq.sso.controller;

import com.hq.sso.model.User;
import com.hq.sso.service.UserService;
import com.hq.sso.utils.CookieUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

////1.www.baidu.com,代理检测到没登录，跳转到本页面，action=verifylogin&loginpage=https://login.baidu.com；
////2.1verifylogin检测到已登录，把cookie中的usertoken带做参数跳转到https://login.baidu.com/?baibaomensso=123456；
////2.2代理检测到百度登录页面即将输出，拦截后后台用webclient根据baibaomensso访问本页action=getuserinfo&baibaomen=123456，后台将返回其用户在百度的账号、密码。代理获取后，改造登录页面，在输入框中填入账号密码，隐藏相关控件后自动提交登录，从而完成到百度的自动登录。
////3.1verifylogin检测到未登录，跳转到登录页面，url带上登录成功后的跳转站点。
////3.2登录页面提交到login，完成登录，写sso cookie，把cookie中的usertoken带做参数跳转到https://login.baidu.com/?baibaomensso=123456.

@Controller
public class SSOController {

    @Autowired
    private UserService userService;

    @RequestMapping("/")
    public String index(HttpServletRequest request, HttpServletResponse response) {
        CookieUtils.removeCookie(request, response, "baibaomensso");
        return "login";
    }

    /**
     * 登录页面提交登录请求。
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/login")
    public String handleLogin(HttpServletRequest request, HttpServletResponse response) {
        return "login";
    }

    @RequestMapping("/chekLogin")
    @ResponseBody
    public String chekLogin(HttpServletRequest request, HttpServletResponse response) {
        String userName = request.getParameter("account");
        String password = request.getParameter("pwd");
        User account = userService.getUser(userName, password);
        if (account != null) {
            //8 登录成功，创建用户账号对应的token xxx
            String token = userService.getTokenForAccount(account);

            //9 把token写到本站cookie；
            CookieUtils.setCookie(response, "baibaomensso", token);

            //这个cookie和sso流程无关，是方便SSO的login.html前端页面显示用户名用的。
            CookieUtils.setCookie(response, "username", account.getName());

            //9 跳转到returnurl并带上token。此处只输出token，在前端页面回调中执行跳转。
            return token;
        }
        return "login";
    }


    /**
     * 子站点通过浏览器跳转过来的SSO请求。
     *
     * @param request
     * @return
     */
    @RequestMapping("/sso")
    public String handleSso(HttpServletRequest request) {
        String token = CookieUtils.getCookieValue(request, "baibaomensso");
        String returnurl = request.getParameter("returnurl");
        System.out.println("returnurl="+returnurl);
        System.out.println("token="+token);
        if (token != null && userService.findAccountForToken(token) != null) {
            System.out.println("redirect="+("redirect:" + this.makeReturnUrl(returnurl, token)));
            return "redirect:" + this.makeReturnUrl(returnurl, token);
        }
        return "redirect:/login?returnurl=" + returnurl;
    }

    /**
     * 注销登录。
     *
     * @return
     */
    @RequestMapping("/logout")
    public String handleLogout() {
        System.out.println("logout==");
        return "redirect:/login?action=logout";
    }

    @RequestMapping("/delete-session")
    public void handleDeleteSession(HttpServletRequest request, HttpServletResponse response) {
        CookieUtils.removeCookie(request, response, "baibaomensso");
        CookieUtils.removeCookie(request, response, "username");
    }

    @RequestMapping("/validate")
    @ResponseBody
    public User handleValidate(HttpServletRequest request) {
        String token = decryptTokenForValidationRequest(request);
        if(token==null){
            return null;
        }
        User user = userService.findAccountForToken(token);
        //todo:实际场景中，应该根据请求的server-key，只传递该server能看到的用户信息。
        return user;
    }

    private String makeReturnUrl(String returnUrlQuery, String token) {
        return returnUrlQuery.contains("?") ? String.format("%s&baibaomensso=%s", returnUrlQuery, token) : String.format("%s?baibaomensso=%s", returnUrlQuery, token);
    }

    /**
     * 解密Validation请求并返回匹配的用户信息。
     * 真实场景中，应根据server-key找到对应的secret，用它解密出待验证的token。
     *
     * @param request
     * @return
     */
    private String decryptTokenForValidationRequest(HttpServletRequest request) {
        return request.getParameter("baibaomensso");
    }

}
